function Weights = holdings2weights(Holdings, Prices, Budget)
%HOLDINGS2WEIGHTS Convert portfolio holdings into portfolio weights.
% Convert portfolio holdings into portfolio weights, where it is assumed that
% the weights must satisfy a budget constraint such that the weights sum to
% Budget (which has a default value of 1) for each portfolio.
%
%	Weights = holdings2weights(Holdings, Prices);
%	Weights = holdings2weights(Holdings, Prices, Budget);
%
% Inputs:
%   Holdings - A NUMPORTS x NUMASSETS matrix with the holdings of NUMPORTS
%		portfolios that contain NUMASSETS assets.
%	Prices - A NUMASSETS vector with NUMASSETS asset prices.
%
% Optional Inputs:
%	Budget - Either a NUMPORTS vector with NUMPORTS budget constraints for each
%		portfolio or a scalar budget constraint to be applied to all portfolios,
%		where every budget constraint must be non-zero. The default budget
%		constraint is 1.
%
% Outputs:
%	Weights - A NUMPORTS x NUMASSETS matrix that contains the normalized
%		weights of NUMPORTS portfolios that contain NUMASSETS assets.
%
% Notes:
%   Holdings may be negative-valued to indicate short positions but overall
%	portfolio weights must necessarily satisfy a non-zero budget constraint.
%
%	The Weights in each portfolio sum to Budget (which is 1 if no Budget is
%	specified).
%
%	See also WEIGHTS2HOLDINGS

%	Copyright 2005 The MathWorks, Inc.
%	$Revision: 1.1.6.1 $ $Date: 2005/11/11 16:21:33 $

if nargin < 3
	Budget = [];
end
if nargin < 2
	error('Finance:holdings2weights:MissingInputArg', ...
		'Missing required input arguments Holdings or Prices.');
end

if isempty(Holdings)
	error('Finance:holdings2weights:EmptyHoldingsMatrix', ...
		'Holdings matrix is empty - cannot continue.');
end

if isempty(Prices)
	error('Finance:holdings2weights:EmptyPriceVector', ...
		'Price vector is empty - cannot continue.');
end

[NumPorts, NumAssets] = size(Holdings);

if isvector(Prices)
	Prices = Prices(:)';
	if (numel(Prices) ~= NumAssets)
		error('Finance:holdings2weights:InconsistentDims', ...
			'Invalid number of asset Prices.');
	end
else
	error('Finance:holdings2weights:InvalidPriceVector', ...
		'Prices should be a vector - cannot continue.');
end

if isvector(Budget)
	Budget = Budget(:);
	[i, j] = size(Budget);
	if any(Budget == 0.0)
		error('Finance:holdings2weights:InvalidBudget', ...
			'Budget constraints should be non-zero.');
	end
	if (i == 1)
		Budget = repmat(Budget,NumPorts,1);
	elseif (i ~= NumPorts)
		error('Finance:holdings2weights:InvalidBudget', ...
			'Budget should be either a scalar or a vector with NumPorts elements.');
	end
else
	Budget = ones(NumPorts,1);
end
	
Weights = zeros(NumPorts, NumAssets);

for i = 1:NumPorts
	Norm = sum(Prices .* Holdings(i,:));
	Weights(i,:) = Budget(i) .* (Prices .* Holdings(i,:)) ./ Norm;
end
